/**
 * 通用工具函数库
 */

/**
 * 防抖函数
 * @param func 要防抖的函数
 * @param wait 等待时间（毫秒）
 * @param immediate 是否立即执行
 * @returns 防抖后的函数
 */
export function debounce<T extends (...args: any[]) => any>(
    func: T,
    wait: number,
    immediate = false
): (...args: Parameters<T>) => void {
    let timeout: ReturnType<typeof setTimeout> | null = null
    
    return function executedFunction(...args: Parameters<T>) {
        const later = () => {
            timeout = null
            if (!immediate) func(...args)
        }
        
        const callNow = immediate && !timeout
        
        if (timeout) clearTimeout(timeout)
        timeout = setTimeout(later, wait)
        
        if (callNow) func(...args)
    }
}

/**
 * 节流函数
 * @param func 要节流的函数
 * @param limit 时间间隔（毫秒）
 * @returns 节流后的函数
 */
export function throttle<T extends (...args: any[]) => any>(
    func: T,
    limit: number
): (...args: Parameters<T>) => void {
    let inThrottle: boolean
    
    return function executedFunction(...args: Parameters<T>) {
        if (!inThrottle) {
            func(...args)
            inThrottle = true
            setTimeout(() => (inThrottle = false), limit)
        }
    }
}

/**
 * 深拷贝对象
 * @param obj 要拷贝的对象
 * @returns 深拷贝后的对象
 */
export function deepClone<T>(obj: T): T {
    if (obj === null || typeof obj !== 'object') {
        return obj
    }
    
    if (obj instanceof Date) {
        return new Date(obj.getTime()) as T
    }
    
    if (obj instanceof Array) {
        return obj.map(item => deepClone(item)) as T
    }
    
    if (typeof obj === 'object') {
        const clonedObj = {} as T
        for (const key in obj) {
            if (obj.hasOwnProperty(key)) {
                clonedObj[key] = deepClone(obj[key])
            }
        }
        return clonedObj
    }
    
    return obj
}

/**
 * 生成唯一ID
 * @param prefix 前缀
 * @returns 唯一ID字符串
 */
export function generateId(prefix = 'id'): string {
    return `${prefix}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
}

/**
 * 格式化文件大小
 * @param bytes 字节数
 * @param decimals 小数位数
 * @returns 格式化后的文件大小字符串
 */
export function formatFileSize(bytes: number, decimals = 2): string {
    if (bytes === 0) return '0 Bytes'
    
    const k = 1024
    const dm = decimals < 0 ? 0 : decimals
    const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
    
    const i = Math.floor(Math.log(bytes) / Math.log(k))
    
    return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]
}

/**
 * 获取URL参数
 * @param name 参数名
 * @param url URL字符串，默认为当前页面URL
 * @returns 参数值或null
 */
export function getUrlParam(name: string, url?: string): string | null {
    const targetUrl = url || window.location.href
    const urlObj = new URL(targetUrl)
    return urlObj.searchParams.get(name)
}

/**
 * 设置URL参数
 * @param name 参数名
 * @param value 参数值
 * @param url URL字符串，默认为当前页面URL
 * @returns 新的URL字符串
 */
export function setUrlParam(name: string, value: string, url?: string): string {
    const targetUrl = url || window.location.href
    const urlObj = new URL(targetUrl)
    urlObj.searchParams.set(name, value)
    return urlObj.toString()
}

/**
 * 删除URL参数
 * @param name 参数名
 * @param url URL字符串，默认为当前页面URL
 * @returns 新的URL字符串
 */
export function removeUrlParam(name: string, url?: string): string {
    const targetUrl = url || window.location.href
    const urlObj = new URL(targetUrl)
    urlObj.searchParams.delete(name)
    return urlObj.toString()
}

/**
 * 判断是否为移动设备
 * @returns 是否为移动设备
 */
export function isMobile(): boolean {
    return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
        navigator.userAgent
    )
}

/**
 * 复制文本到剪贴板
 * @param text 要复制的文本
 * @returns Promise<boolean> 是否复制成功
 */
export async function copyToClipboard(text: string): Promise<boolean> {
    try {
        if (navigator.clipboard && window.isSecureContext) {
            await navigator.clipboard.writeText(text)
            return true
        } else {
            // 降级方案
            const textArea = document.createElement('textarea')
            textArea.value = text
            textArea.style.position = 'fixed'
            textArea.style.left = '-999999px'
            textArea.style.top = '-999999px'
            document.body.appendChild(textArea)
            textArea.focus()
            textArea.select()
            const result = document.execCommand('copy')
            document.body.removeChild(textArea)
            return result
        }
    } catch (error) {
        console.error('复制失败:', error)
        return false
    }
}

/**
 * 数字格式化（添加千分位分隔符）
 * @param num 数字
 * @param separator 分隔符，默认为逗号
 * @returns 格式化后的字符串
 */
export function formatNumber(num: number, separator = ','): string {
    return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, separator)
}

/**
 * 验证邮箱格式
 * @param email 邮箱地址
 * @returns 是否为有效邮箱
 */
export function isValidEmail(email: string): boolean {
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
    return emailRegex.test(email)
}

/**
 * 验证手机号格式（中国大陆）
 * @param phone 手机号
 * @returns 是否为有效手机号
 */
export function isValidPhone(phone: string): boolean {
    const phoneRegex = /^1[3-9]\d{9}$/
    return phoneRegex.test(phone)
}

/**
 * 验证身份证号格式（中国大陆）
 * @param idCard 身份证号
 * @returns 是否为有效身份证号
 */
export function isValidIdCard(idCard: string): boolean {
    const idCardRegex = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/
    return idCardRegex.test(idCard)
}